<?php
/**
 * Note: *
 * Date: 2021/2/21
 * Time: 22:07
 */
namespace App\Http\Controllers\Admin;

use App\Caches\ManagerCache;
use App\Constants\WechatConstant;
use App\Models\Manager;
use App\Models\ManagerOauthRelation;
use App\Services\GatewayWorkerService;
use App\Services\Wechat\OfficialAccountService;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class ManagerController extends CurdController
{
    protected string $classModel = Manager::class;

    protected array $searchFields = [
        'username' => self::FIELD_TYPE_LIKE,
        'email' => self::FIELD_TYPE_LIKE,
        'mobile' => self::FIELD_TYPE_LIKE,
        'name' => self::FIELD_TYPE_LIKE,
        'role' => self::FIELD_TYPE_JSON_CONTAINS_NUMERIC_ANY
    ];

    protected array $relationWiths = [
        'roles',
        'creator'
    ];

    public function index(Request $request)
    {
        // 非超管只能看见自己创建的账号
        if (!in_array(1, $this->user->role)) {
            $this->searchFields = array_merge($this->searchFields, ['creator_id' => self::FIELD_TYPE_NUMERIC]);
            $this->request->merge(['creator_id' => $this->user->id]);
        }

        return $this->myIndex();
    }

    /**
     * @param Request $request
     */
    public function storeBefore(Request $request)
    {
        $this->request->merge(['creator_id' => $this->user->id]);
        $rules = [
            'username' => "required|unique:{$this->model->getTable()}",
            'password' => 'required',
            'name' => 'required',
        ];
        $roleRules = $this->getRoleRules();
        $request->validate(array_merge($rules, $roleRules['rules']), $roleRules['message']);
    }

    /**
     * @param Request $request
     */
    public function updateBefore(Request $request)
    {
        $rules = [
            'username' => "required|unique:{$this->model->getTable()},username,".$request->id,
            'name' => 'required',
        ];
        $roleRules = $this->getRoleRules();
        $request->validate(array_merge($rules, $roleRules['rules']), $roleRules['message']);
    }

    /**
     * 获取当前登录用户信息
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function info()
    {
        $this->user->append('created_role_ids');
        return responseData($this->user);
    }

    /**
     * 清除session并删除token
     * @param Request $request
     */
    public function logout(Request $request)
    {
        auth('web')->logout();
        $this->user->tokens()->delete();
    }

    /**
     * 生成 登录二维码
     * @param Request $request
     * @param OfficialAccountService $service
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function getBindQrcode(Request $request)
    {
        $request->validate([
            'client_id' => 'required',
            'channel' => 'required|in:wechat',
        ]);

        $url = '';
        $ttl = 600;
        if ($request->channel === 'wechat') {
            $service = new OfficialAccountService();
            $qrcodeInfo = ['client_id' => $request->client_id, 'manager_id' => $this->user->id];
            $url = $service->getQrcodeTemporary(WechatConstant::EVENT_ADMIN_BIND, $qrcodeInfo, $ttl);
        }

        return responseData([
            'channel' => $request->channel,
            'url' => $url,
            'ttl' => $ttl,
        ]);
    }

    /**
     * 收到二维码消息
     * @param string $channel
     * @param string $openid
     * @param array $qrcodeInfo
     * @return bool
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function bindQrcodeReceive(string $channel, string $openid, array $qrcodeInfo): bool
    {
        $manager = Manager::find($qrcodeInfo['manager_id']);
        $createData = [
            'openid' => $openid,
            'unionid' => '',
            'nickname' => '',
            'avatar' => '',
        ];

        // 更新头像
        if ($channel === 'wechat') {
            if (ManagerOauthRelation::whereChannel($channel)->whereOpenid($openid)->where('manager_id', '<>', $manager->id)->exists()) {
                throw new \Exception('该微信号已经绑定其他用户');
            }
            $service = new OfficialAccountService();
            try {
                $wxuser = $service->getUser($openid);
            } catch (\Exception $e) {
                report($e);
                throw new \Exception('获取微信用户信息失败, 请稍后再试');
            }

            if ($wxuser->headimgurl) $manager->avatar = $wxuser->headimgurl;
            if ($manager->isDirty()) $manager->save();

            $createData = [
                'openid' => $openid,
                'unionid' => $wxuser->unionid ?: '',
                'nickname' => $wxuser->nickname,
                'avatar' => $wxuser->headimgurl,
            ];
        }

        $manager->oauthRelations()->updateOrCreate([
            'channel' => $channel,
        ], $createData);

        ManagerCache::setOpenid($qrcodeInfo['client_id'], $channel, $openid);
        return true;
    }

    /**
     * 查询绑定结果
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function bindQuery(Request $request)
    {
        $openid = ManagerCache::getOpenid($request->client_id, $request->channel);
        if ($openid) ManagerCache::delOpenid($request->client_id, $request->channel);
        return responseData(!!$openid);
    }

    /**
     * 简单更新 仅更新部分字段
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function updateSimple(Request $request)
    {
        $data = $request->only(['password', 'email', 'mobile']);
        if (empty($data['password'])) unset($data['password']);
        $this->user->fill($data);
        $this->user->save();
        return responseMessage();
    }

    /**
     * @return array
     */
    protected function getRoleRules()
    {
        if (in_array(1, $this->user->role)) {
            return [
                'rules' => [],
                'message' => []
            ];
        }
        return [
            'rules' => [
                'role' => 'array',
                'role.*' => Rule::in($this->user->getAllowedRoles()),
            ],
            'message' => [
                'role.*.in' => '当前勾选的用户权限不在管理范围内，请联系系统管理员'
            ],
        ];
    }
}
